// <!-- TODO Set    类似于数组的数据结构，成员值都是唯一且没有重复的值-->
// 入参  具有Iterator接口的数据结构
var set1 = new Set([1, 2, 1])
var set2 = new Set([2, 3, 4, 5])
var set3 = new Set(document.querySelectorAll('div'))

// 属性
set1.constructor //返回Set
set1.size //返回实例成员总数

// 方法
set1.add(1) // 添加值，返回实例
set1.delete() // 删除值，返回布尔
set1.has() // 检查值，返回布尔
set1.clear() // 清除所有成员
set1.keys() // 返回以属性值为遍历器的对象
set1.values() // 返回以属性值为遍历器的对象
set1.entries() // 返回以属性值和属性值为遍历器的对象
set1.forEach(() => {}) // 使用回调函数遍历每个成员

// 应用场景
// 去重字符串：
;[...new Set('1231')].join('') // [1,2,3]
// 去重数组：
;[...new Set(set1)]
// 并集：
new Set([...set1, ...set2])
// 交集：
new Set([...set1].filter(v => set2.has(v)))

// 重点难点
// 没有键只有值，可认为键和值两值相等
// 添加多个NaN时，只会存在一个NaN

// <!-- TODO WeakSet     和Set结构类似，成员值只能是对象-->
// 入参具有Iterator接口的数据结构属性
var weakSet1 = new WeakSet([{}, {}, {}])
var weakSet2 = new WeakSet(document.querySelectorAll('div'))

// 属性
weakSet1.constructor //返回WeakSet

// 方法
weakSet1.add({}) //添加值，返回实例
weakSet1.delete() //删除值，返回布尔
weakSet1.has() //检查值，返回布尔

// 应用场景
// 弱引用 - 储存DOM节点：DOM节点被移除时自动释放此成员，不用担心这些节点从文档移除时会引发内存泄漏
// 弱引用 - 临时存放一组对象或存放跟对象绑定的信息：只要这些对象在外部消失，它在WeakSet结构中的引用就会自动消
var a = {}
var b = a
a = null
console.log(b) // {}

var a = [1] 
var b = new WeakSet([a])
a = null
console.log(b) 
// WeakSet {} 结果b是一个空的WeakSet，因为a已经被释放了，
// 但是浏览器显示结果是WeakSet {<1>}，因为浏览器的垃圾回收我们不能控制什么时候执行，可以通过控制台主动回收Memory

// 重点难点
// 成员都是弱引用，垃圾回收机制不考虑WeakSet结构对此成员的引用
// 成员不适合引用，它会随时消失，因此ES6规定WeakSet结构不可遍历
// 其他对象不再引用成员时，垃圾回收机制会自动回收此成员所占用的内存，不考虑此成员是否还存在于WeakSet结构中

// <!-- TODO Map     类似于对象的数据结构，成员键是任何类型的值-->
// 入参具有Iterator接口且每个成员都是一个双元素数组的数据结构
var map = new Map()

// 属性
map.constructor //构造函数，返回Map
map.size // 返回实例成员总数

// 方法
map.get() // 返回键值对
map.set() // 添加键值对，返回实例
map.delete() // 删除键值对，返回布尔
map.has() // 检查键值对，返回布尔
map.clear() // 清除所有成员
map.keys() // 返回以键为遍历器的对象
map.values() // 返回以值为遍历器的对象
map.entries() // 返回以键和值为遍历器的对象
map.forEach(() => {}) // 使用回调函数遍历每个成员

// 重点难点
// 键跟内存地址绑定，只要内存地址不一样就视为两个键
// Object结构提供字符串—值的对应，Map结构提供值—值的对应

// <!-- TODO WeakMap     和Map结构类似，成员键只能是引用类型-->
// 入参：具有Iterator接口且每个成员都是一个双元素数组的数据结构
var weakMap = new WeakMap()

// 属性
weakMap.constructor // 构造函数，返回WeakMap

// 方法
weakMap.get() // 返回键值对
weakMap.set({}) // 添加键值对，返回实例
weakMap.delete() // 删除键值对，返回布尔
weakMap.has() // 检查键值对，返回布尔

// 应用场景
// 储存DOM节点：DOM节点被移除时自动释放此成员键，不用担心这些节点从文档移除时会引发内存泄漏
// 部署私有属性：内部属性是实例的弱引用，删除实例时它们也随之消失，不会造成内存泄漏

// 重点难点
// 成员键都是弱引用，垃圾回收机制不考虑WeakMap结构对此成员键的引用
// 成员键不适合引用，它会随时消失，因此ES6规定WeakMap结构不可遍历
// 其他对象不再引用成员键时，垃圾回收机制会自动回收此成员所占用的内存，不考虑此成员是否还存在于WeakMap结构中
// 一旦不再需要，成员会自动消失，不用手动删除引用
// 弱引用的只是键而不是值，值依然是正常引用
// 即使在外部消除了成员键的引用，内部的成员值依然存在

// 例子 弱引用 -
let wm = new WeakMap()
let obj = { age: '1' }
wm.set(obj, 'some information')
console.log(wm.get(obj)) // "some information"
obj = null // 清除引用
console.log(wm.get(obj)) // undefined
// 注意，如果打印 wm 对象，有时会显示 ，但是实际取不到，这和v8机制有关
